/*
 * matrix.cpp
 *
 *  Created on: 10 May 2012
 *      Author: hframe
 */

#include "matrix.h"

startnamespace(androidplus)startnamespace(drawing)

matrix::matrix() {
	data=new t_float[16];
	temp=new t_float[16];
	memset(data,0,16*sizeof(t_float));

}
matrix::matrix(const matrix &m):data(new t_float[16]),temp(new t_float[16]) {
	memcpy(data,m.data,16*sizeof(t_float));

}

matrix::matrix(t_float *array,t_uint8 lenght){
	memcpy(data,array,lenght*sizeof(t_float));
}
matrix& matrix::operator=(const matrix &m) {
	memcpy(data,m.data,16*sizeof(t_float));

	return *this;
}
matrix::~matrix() {
	delete[] data;
}
t_float& matrix::operator[]( t_uint32 index) {
	return data[index];
}

t_bool matrix::operator==(const matrix &m) {
	return memcmp(data,m.data,16*sizeof(t_float));
}
/*matrix& matrix::operator+(const matrix &m) {
	for(t_int32 i=0;i<16;++i)
	data[i]+=m.data[i];
	return *this;
}
matrix& matrix::operator/(const matrix &m) {
	for(t_int32 i=0;i<16;++i)
	data[i]/=m.data[i];
	return *this;
}
matrix& matrix::operator*(const matrix &m) {
	for(t_int32 i=0;i<16;++i)
	data[i]*=m.data[i];
	return *this;
}
matrix& matrix::operator-(const matrix &m) {
	for(t_int32 i=0;i<16;++i)
	data[i]-=m.data[i];
	return *this;
}
matrix& matrix::operator+(t_float val) {
	for(t_int32 i=0;i<16;++i)
	data[i]+=val;
	return *this;
}
matrix& matrix::operator/(t_float val) {
	for(t_int32 i=0;i<16;++i)
	data[i]/=val;
	return *this;
}
matrix& matrix::operator*(t_float val) {
	for(t_int32 i=0;i<16;++i)
	data[i]*=val;
	return *this;
}
matrix& matrix::operator-(t_float val) {
	for(t_int32 i=0;i<16;++i)
	data[i]/=val;
	return *this;
}

matrix& matrix::operator+=(const matrix &m) {
	return *this=*this + m;
}
matrix& matrix::operator/=(const matrix &m) {
	return *this=*this / m;
}
matrix& matrix::operator*=(const matrix &m) {
	return *this= *this * m;
}
matrix& matrix::operator-=(const matrix &m) {
	return *this= *this - m;
}
matrix& matrix::operator+=(t_float val) {
	return *this= *this +val;
}
matrix& matrix::operator/=(t_float val) {
	return *this= *this / val;
}
matrix& matrix::operator*=(t_float val) {
	return *this= *this * val;
}
matrix& matrix::operator-=(t_float val) {
	return *this= *this - val;
}*/

matrix matrix::operator*(const matrix &m){
	matrix tmp;
	matrix tmp2(m);
	for (int i=0; i<4; i++)
		{
			tmp[i*4+0] =
							(data[i*4+0] * tmp2[0*4+0]) +
							(data[i*4+1] * tmp2[1*4+0]) +
							(data[i*4+2] * tmp2[2*4+0]) +
							(data[i*4+3] * tmp2[3*4+0]) ;

			tmp[i*4+1] =
							(data[i*4+0] * tmp2[0*4+1]) +
							(data[i*4+1] * tmp2[1*4+1]) +
							(data[i*4+2] * tmp2[2*4+1]) +
							(data[i*4+3] * tmp2[3*4+1]) ;

			tmp[i*4+2] =
							(data[i*4+0] * tmp2[0*4+2]) +
							(data[i*4+1] * tmp2[1*4+2]) +
							(data[i*4+2] * tmp2[2*4+2]) +
							(data[i*4+3] * tmp2[3*4+2]) ;

			tmp[i*4+3] =
							(data[i*4+0] * tmp2[0*4+3]) +
							(data[i*4+1] * tmp2[1*4+3]) +
							(data[i*4+2] * tmp2[2*4+3]) +
							(data[i*4+3] * tmp2[3*4+3]) ;
		}
	return tmp;
}

t_float * matrix::to_float_array(){

  return this->data;
	temp[0]=data[0];
	temp[1]=data[4];
	temp[2]=data[8];
	temp[3]=data[12];

	temp[4]=data[1];
		temp[5]=data[5];
		temp[6]=data[9];
		temp[7]=data[13];

		temp[8]=data[2];
			temp[9]=data[6];
			temp[10]=data[10];
			temp[11]=data[14];

			temp[12]=data[3];
				temp[13]=data[7];
				temp[14]=data[11];
				temp[15]=data[15];



	return this->temp;
}

matrix& matrix::scale(t_float x,t_float y,t_float z) {
	data[0] *= x;
	data[1] *= x;
	data[2] *= x;
	data[3] *= x;

	data[4] *= y;
	data[5] *= y;
	data[6] *= y;
	data[7] *= y;

	data[8] *= z;
	data[9] *= z;
	data[10] *= z;
	data[11] *= z;

	return *this;
}
matrix& matrix::rotate(t_float angle, t_float x,t_float y,t_float z) {

#define PI 3.1415926535897932384626433832795f

	t_float sinAngle, cosAngle;
	t_float mag = sqrtf(x * x + y * y + z * z);

	sinAngle = sinf ( angle * PI / 180.0f );
	cosAngle = cosf ( angle * PI / 180.0f );
	if ( mag > 0.0f )
	{
		t_float xx, yy, zz, xy, yz, zx, xs, ys, zs;
		t_float oneMinusCos;
		matrix rotMat;

		x /= mag;
		y /= mag;
		z /= mag;

		xx = x * x;
		yy = y * y;
		zz = z * z;
		xy = x * y;
		yz = y * z;
		zx = z * x;
		xs = x * sinAngle;
		ys = y * sinAngle;
		zs = z * sinAngle;
		oneMinusCos = 1.0f - cosAngle;

		rotMat[0] = (oneMinusCos * xx) + cosAngle;
		rotMat[1] = (oneMinusCos * xy) - zs;
		rotMat[2] = (oneMinusCos * zx) + ys;
		rotMat[3] = 0.0F;

		rotMat[4] = (oneMinusCos * xy) + zs;
		rotMat[5] = (oneMinusCos * yy) + cosAngle;
		rotMat[6] = (oneMinusCos * yz) - xs;
		rotMat[7] = 0.0F;

		rotMat[8] = (oneMinusCos * zx) - ys;
		rotMat[9] = (oneMinusCos * yz) + xs;
		rotMat[10] = (oneMinusCos * zz) + cosAngle;
		rotMat[11] = 0.0F;

		rotMat[12] = 0.0F;
		rotMat[13] = 0.0F;
		rotMat[14] = 0.0F;
		rotMat[15] = 1.0F;
		//*this *=rotMat;

	}
	return *this;

}
matrix& matrix::transform(t_float x,t_float y,t_float z) {
	data[12] += (data[0] * x + data[4] * y + data[8] * z);
	data[13] += (data[1] * x + data[5] * y + data[9] * z);
	data[14] += (data[2] * x + data[6] * y + data[10] * z);
	data[15] += (data[3] * x + data[7] * y + data[11] * z);
	return *this;

}

matrix matrix::matrix_identity() {
	matrix m;
	m[0]=1;
	m[5]=1;
	m[10]=1;
	m[15]=1;
	return m;

}
 t_float matrix::length(t_float x,t_float y,t_float z){
	return sqrt(x*x+y*y+z*z);
}


endnamespace(drawing)
endnamespace(androidplus)
